package com.onpositive.data.serializer.readers;

import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.util.BitSet;
import java.util.LinkedHashSet;

import com.onpositive.data.FilterTester;
import com.onpositive.data.serializer.writers.AbstractWriter;
import com.onpositive.data.serializer.writers.DoubleWriter;


public class DoubleReader extends CollectionReader<Double>{
	
//	private static final int DOUBLE_SIZE = 8 ;
	private static final double defaultValue = Double.NaN ;
	private double[] primitiveValuesArrays;

	public DoubleReader(){
		super( Double.class );
	}
	
	@Override
	protected void initValuesAray(byte[] byteData) {
		
		primitiveValuesArrays = new double[size];
		
		ByteBuffer bBuf = ByteBuffer.wrap( byteData ) ;
		
		boolean continueIteration = true ;
		int start = 0 ;
		int end = emptyCells.nextSetBit(0) ;
		for(  ; continueIteration ;  )
		{			
			for( int i = start ; i < end ; i++ )
				primitiveValuesArrays[i] = bBuf.getDouble() ;			

			if( end < size )
				primitiveValuesArrays[end] = defaultValue ;

			start = end+1 ;
			end = emptyCells.nextSetBit( start ) ;
			end = end >= 0 ? end : size ;
			continueIteration = start <= size ;			
		}
	}
	
	@Override
	protected Double doGet( int i )
	{
		double d = primitiveValuesArrays[i];
		if (d==defaultValue){
			return null;
		}
		return d;
				
	}
	
	@Override
	protected Double defaultObject() {
		return defaultValue;
	}

	@Override
	protected Double readObject(ByteBuffer bBuf) {

		return bBuf.getDouble();
	}

	@Override
	public void filterOut(LinkedHashSet<Object> obj, String text) {
		
	}
	
	@Override
	public boolean accept(int op, int a, Object constraint) {
		if( !isInitialized() )
			init() ;
		boolean b = emptyCells.get(a);
		if (constraint == null) {
			switch (op) {
			case FilterTester.GE:
			case FilterTester.LE:
			case FilterTester.EQ:
				return b;

			case FilterTester.NEQ:
				return !b;

			default:
				break;
			}
			return false;
		}
		if (b) {			
			return false;
		}

		double i = primitiveValuesArrays[a];

		Number m = (Number) constraint;
		int ww = m.intValue();
		switch (op) {
		case FilterTester.EQ:
			return ww == i;
		case FilterTester.NEQ:
			return ww != i;
		case FilterTester.LE:
			return ww >= i;
		case FilterTester.LT:
			return ww > i;
		case FilterTester.GT:
			return ww < i;
		case FilterTester.GE:
			return ww <= i;
		case FilterTester.CONTAINS:
			return ww == i;
		default:
			throw new UnsupportedOperationException();
		}
	}
	@Override
	public Object aggregate(int op, BitSet ss) {
		double str=0.0;
		if (!isInitialized()){
			init();
		}
		new DoubleAggregator(op).getAggregatedValue(primitiveValuesArrays, ss, ss);
		return str;
	}

	@Override
	public void setValue(int num, Object value) {
		primitiveValuesArrays[num]=((Number)value).doubleValue();
	}

	@Override
	public AbstractWriter<Double> getWriter() {
		return new DoubleWriter();
	}

	@Override
	public void initEmpty(int dataSize) {
		primitiveValuesArrays=new double[dataSize];
		setInitialized();
	}

	@Override
	public void expand(int newSize) {
		if (!isInitialized()){
			init();
		}
		double[] m=new double[newSize];
		System.arraycopy(primitiveValuesArrays, 0, m, 0, primitiveValuesArrays.length);
		for (int a=primitiveValuesArrays.length;a<m.length;a++){
			m[a]=defaultValue;
		}
		primitiveValuesArrays=m;
	}
}
